This project uses GDP dataset downloaded from the WorldBank Database. The dataset can be accessed in GitHub Repository

1 Part A: Loading libraries and data pre-processing

1.1 Libraries

knitr::opts_chunk$set(echo = TRUE)

library(tidyverse)
library(janitor)
library(gganimate)
#install.packages("gifski")
library(gifski)
library(readr)

1.2 Load GDP data

gdp <- read_delim("gdp_ori.csv", 
    ";", escape_double = FALSE, trim_ws = TRUE)
## Parsed with column specification:
## cols(
##   .default = col_double(),
##   country_name = col_character(),
##   country_code = col_character(),
##   Region = col_character(),
##   indicator_name = col_character()
## )
## See spec(...) for full column specifications.
head(gdp)
gdp

Drop non-country rows

gdp_balance <- filter(gdp, !(country_code %in% c("ARB", "CEB", "CSS","EAP", "EAR", "EAS", "ECA", "ECS", "EMU", "EUU", "FCS", "HIC", "HPC", "IBD", "IBT", "IDA", "IDB", "IDX", "INX", "LAC", "LCN", "LDC", "LIC", "LMC", "LMY", "LTE", "MIC", "MEA", "MNA", "NAC", "OED", "OSS", "PST", "PSS", "PRE", "SSA", "SSF", "TEA", "TLA", "TMN", "TSA", "TSS", "UMC", "WLD")))
gdp_balance

Drop all rows with NA in “Region” column

gdp_balance <- subset(gdp_balance, !is.na(Region))
gdp_balance

Transform the dataframe into long shape

gdp_long <- gdp_balance %>% 
  mutate_at(vars(contains("yr")),as.numeric) %>% 
  gather(year,gdp,5:54)

1.3 Save the dataframe that is ready to use

write_csv(gdp_long, "gdp_ready.csv")

2 Part B: Building the static plots using ggplot

2.1 Import the ready-to-use data

gdp_ready <- read_csv("gdp_ready.csv")
## Parsed with column specification:
## cols(
##   country_name = col_character(),
##   country_code = col_character(),
##   Region = col_character(),
##   indicator_name = col_character(),
##   year = col_double(),
##   gdp = col_double()
## )
gdp_ready
gdp_set <- gdp_ready %>%
  group_by(year) %>%
  mutate(rank = rank(-gdp),
         gdp_rel = gdp/gdp[rank==1],
         gdp_lbl = paste0(" ",round(gdp/1e9))) %>%
  group_by(country_name) %>% 
  filter(rank <=30) %>%
  ungroup()
static_plot <- ggplot(gdp_set, aes(rank, group = country_name)) +  
  geom_tile(aes(y = gdp/2,
                height = gdp, fill = Region,
                width = 0.9), alpha = 0.8, color = NA) +
  geom_text(aes(y = 0, label = paste(country_name, " ")), vjust = 0.2, hjust = 1) +
  geom_text(aes(y=gdp,label = gdp_lbl, hjust=0)) +
  geom_text(aes(x=30, y=max(gdp) , label = as.factor(year)), vjust = 0.2, alpha = 0.5,  col = "gray", size = 20) +
  coord_flip(clip = "off", expand = FALSE) +
  scale_y_continuous(labels = scales::comma) +
  scale_x_reverse() +
  scale_fill_discrete(guide = guide_legend(title.theme = element_text(
      size = 20), label.theme = element_text(size = 15))) +
  theme(axis.line=element_blank(),
        axis.text.x=element_blank(),
        axis.text.y=element_blank(),
        axis.ticks=element_blank(),
        axis.title.x=element_blank(),
        axis.title.y=element_blank(),
        panel.background=element_blank(),
        panel.border=element_blank(),
        panel.grid.major=element_blank(),
        panel.grid.minor=element_blank(),
        panel.grid.major.x = element_line( size=.1, color="grey" ),
        panel.grid.minor.x = element_line( size=.1, color="grey" ),
        plot.title=element_text(size=25, hjust=0, face="bold", colour="black", vjust=-1),
        plot.subtitle=element_text(size=18, hjust=1, face="italic", color="grey"),
        plot.caption =element_text(size=14, hjust=1, face="italic", color="grey"),
        plot.background=element_blank(),
       plot.margin = margin(2,2, 2, 4, "cm"))

3 Part C: Animating the static plot

animated <- static_plot + transition_states(year,
transition_length = 3, state_length = 0, wrap = FALSE) +
  view_follow(fixed_x = TRUE)  +
  ease_aes('linear')+
    enter_fade()+
    exit_fade() +
  labs(title = 'Top 30 World GDP, 1970-2019',  
       subtitle  =  "GDP in Billions USD",
       caption  = "Data Source: World Bank Data")

3.1 Render the animated chart to .gif file

animate(animated, 150, fps = 5, end_pause = 30, width = 1500, height = 1000, 
        renderer = gifski_renderer("anim_gdp.gif"))

LS0tDQp0aXRsZTogIkNyZWF0aW5nIEFuaW1hdGVkIFJhY2UgQmFyIENoYXJ0IGluIFIiDQphdXRob3I6ICJIYXJyeSBBZ2ludGEiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6DQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIGRmX3ByaW50OiBwYWdlZA0KICAgIHRvYzogdHJ1ZQ0KICAgIHRvY19mbG9hdDoNCiAgICAgIGNvbGxhcHNlZDogZmFsc2UNCiAgICAgIHNtb290aF9zY3JvbGw6IGZhbHNlDQogICAgdG9jX2RlcHRoOiA0DQogICAgbnVtYmVyX3NlY3Rpb25zOiB0cnVlDQogICAgY29kZV9mb2xkaW5nOiAic2hvdyINCiAgICB0aGVtZTogImNvc21vIg0KICAgIGhpZ2hsaWdodDogIm1vbm9jaHJvbWUiDQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KICBodG1sX25vdGVib29rOg0KICAgIGNvZGVfZm9sZGluZzogc2hvdw0KICAgIGhpZ2hsaWdodDogbW9ub2Nocm9tZQ0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogICAgdGhlbWU6IGNvc21vDQogICAgdG9jOiB5ZXMNCiAgICB0b2NfZGVwdGg6IDQNCiAgICB0b2NfZmxvYXQ6DQogICAgICBjb2xsYXBzZWQ6IG5vDQogICAgICBzbW9vdGhfc2Nyb2xsOiBubw0KICB3b3JkX2RvY3VtZW50OiBkZWZhdWx0DQotLS0NCg0KPHN0eWxlPg0KaDEudGl0bGUge2ZvbnQtc2l6ZTogMThwdDsgY29sb3I6IERhcmtCbHVlO30gDQpib2R5LCBoMSwgaDIsIGgzLCBoNCB7Zm9udC1mYW1pbHk6ICJQYWxhdGlubyIsIHNlcmlmO30NCmJvZHkge2ZvbnQtc2l6ZTogMTJwdDt9DQovKiBIZWFkZXJzICovDQpoMSxoMixoMyxoNCxoNSxoNntmb250LXNpemU6IDE0cHQ7IGNvbG9yOiAjMDAwMDhCO30NCmJvZHkge2NvbG9yOiAjMzMzMzMzO30NCmEsIGE6aG92ZXIge2NvbG9yOiAjOEIzQTYyO30NCnByZSB7Zm9udC1zaXplOiAxMnB4O30NCjwvc3R5bGU+DQoNClRoaXMgcHJvamVjdCB1c2VzIEdEUCBkYXRhc2V0IGRvd25sb2FkZWQgZnJvbSB0aGUgV29ybGRCYW5rIERhdGFiYXNlLiBUaGUgZGF0YXNldCBjYW4gYmUgYWNjZXNzZWQgaW4gW0dpdEh1YiBSZXBvc2l0b3J5XShodHRwczovL2dpdGh1Yi5jb20vaGFnaW50YS9hbmltYXRlZC1iYXItY2hhcnQtaW4tUikNCg0KDQojIFBhcnQgQTogTG9hZGluZyBsaWJyYXJpZXMgYW5kIGRhdGEgcHJlLXByb2Nlc3NpbmcNCiMjIExpYnJhcmllcw0KYGBge3IgbWVzc2FnZT1GQUxTRSwgd2FybmluZz1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCg0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGphbml0b3IpDQpsaWJyYXJ5KGdnYW5pbWF0ZSkNCiNpbnN0YWxsLnBhY2thZ2VzKCJnaWZza2kiKQ0KbGlicmFyeShnaWZza2kpDQpsaWJyYXJ5KHJlYWRyKQ0KYGBgDQoNCiMjIExvYWQgR0RQIGRhdGENCmBgYHtyfQ0KZ2RwIDwtIHJlYWRfZGVsaW0oImdkcF9vcmkuY3N2IiwgDQogICAgIjsiLCBlc2NhcGVfZG91YmxlID0gRkFMU0UsIHRyaW1fd3MgPSBUUlVFKQ0KYGBgDQoNCmBgYHtyfQ0KaGVhZChnZHApDQpgYGANCg0KYGBge3J9DQpnZHANCmBgYA0KDQpEcm9wIG5vbi1jb3VudHJ5IHJvd3MNCmBgYHtyfQ0KZ2RwX2JhbGFuY2UgPC0gZmlsdGVyKGdkcCwgIShjb3VudHJ5X2NvZGUgJWluJSBjKCJBUkIiLCAiQ0VCIiwgIkNTUyIsIkVBUCIsICJFQVIiLCAiRUFTIiwgIkVDQSIsICJFQ1MiLCAiRU1VIiwgIkVVVSIsICJGQ1MiLCAiSElDIiwgIkhQQyIsICJJQkQiLCAiSUJUIiwgIklEQSIsICJJREIiLCAiSURYIiwgIklOWCIsICJMQUMiLCAiTENOIiwgIkxEQyIsICJMSUMiLCAiTE1DIiwgIkxNWSIsICJMVEUiLCAiTUlDIiwgIk1FQSIsICJNTkEiLCAiTkFDIiwgIk9FRCIsICJPU1MiLCAiUFNUIiwgIlBTUyIsICJQUkUiLCAiU1NBIiwgIlNTRiIsICJURUEiLCAiVExBIiwgIlRNTiIsICJUU0EiLCAiVFNTIiwgIlVNQyIsICJXTEQiKSkpDQpnZHBfYmFsYW5jZQ0KYGBgDQoNCkRyb3AgYWxsIHJvd3Mgd2l0aCBOQSBpbiAiUmVnaW9uIiBjb2x1bW4NCmBgYHtyfQ0KZ2RwX2JhbGFuY2UgPC0gc3Vic2V0KGdkcF9iYWxhbmNlLCAhaXMubmEoUmVnaW9uKSkNCmdkcF9iYWxhbmNlDQpgYGANCg0KVHJhbnNmb3JtIHRoZSBkYXRhZnJhbWUgaW50byBsb25nIHNoYXBlDQpgYGB7cn0NCmdkcF9sb25nIDwtIGdkcF9iYWxhbmNlICU+JSANCiAgbXV0YXRlX2F0KHZhcnMoY29udGFpbnMoInlyIikpLGFzLm51bWVyaWMpICU+JSANCiAgZ2F0aGVyKHllYXIsZ2RwLDU6NTQpDQpgYGANCg0KIyMgU2F2ZSB0aGUgZGF0YWZyYW1lIHRoYXQgaXMgcmVhZHkgdG8gdXNlDQpgYGB7cn0NCndyaXRlX2NzdihnZHBfbG9uZywgImdkcF9yZWFkeS5jc3YiKQ0KYGBgDQoNCiMgUGFydCBCOiBCdWlsZGluZyB0aGUgc3RhdGljIHBsb3RzIHVzaW5nIGdncGxvdA0KIyMgSW1wb3J0IHRoZSByZWFkeS10by11c2UgZGF0YQ0KYGBge3J9DQpnZHBfcmVhZHkgPC0gcmVhZF9jc3YoImdkcF9yZWFkeS5jc3YiKQ0KZ2RwX3JlYWR5DQpgYGANCg0KYGBge3J9DQpnZHBfc2V0IDwtIGdkcF9yZWFkeSAlPiUNCiAgZ3JvdXBfYnkoeWVhcikgJT4lDQogIG11dGF0ZShyYW5rID0gcmFuaygtZ2RwKSwNCiAgICAgICAgIGdkcF9yZWwgPSBnZHAvZ2RwW3Jhbms9PTFdLA0KICAgICAgICAgZ2RwX2xibCA9IHBhc3RlMCgiICIscm91bmQoZ2RwLzFlOSkpKSAlPiUNCiAgZ3JvdXBfYnkoY291bnRyeV9uYW1lKSAlPiUgDQogIGZpbHRlcihyYW5rIDw9MzApICU+JQ0KICB1bmdyb3VwKCkNCmBgYA0KDQpgYGB7cn0NCnN0YXRpY19wbG90IDwtIGdncGxvdChnZHBfc2V0LCBhZXMocmFuaywgZ3JvdXAgPSBjb3VudHJ5X25hbWUpKSArICANCiAgZ2VvbV90aWxlKGFlcyh5ID0gZ2RwLzIsDQogICAgICAgICAgICAgICAgaGVpZ2h0ID0gZ2RwLCBmaWxsID0gUmVnaW9uLA0KICAgICAgICAgICAgICAgIHdpZHRoID0gMC45KSwgYWxwaGEgPSAwLjgsIGNvbG9yID0gTkEpICsNCiAgZ2VvbV90ZXh0KGFlcyh5ID0gMCwgbGFiZWwgPSBwYXN0ZShjb3VudHJ5X25hbWUsICIgIikpLCB2anVzdCA9IDAuMiwgaGp1c3QgPSAxKSArDQogIGdlb21fdGV4dChhZXMoeT1nZHAsbGFiZWwgPSBnZHBfbGJsLCBoanVzdD0wKSkgKw0KICBnZW9tX3RleHQoYWVzKHg9MzAsIHk9bWF4KGdkcCkgLCBsYWJlbCA9IGFzLmZhY3Rvcih5ZWFyKSksIHZqdXN0ID0gMC4yLCBhbHBoYSA9IDAuNSwgIGNvbCA9ICJncmF5Iiwgc2l6ZSA9IDIwKSArDQogIGNvb3JkX2ZsaXAoY2xpcCA9ICJvZmYiLCBleHBhbmQgPSBGQUxTRSkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXMobGFiZWxzID0gc2NhbGVzOjpjb21tYSkgKw0KICBzY2FsZV94X3JldmVyc2UoKSArDQogIHNjYWxlX2ZpbGxfZGlzY3JldGUoZ3VpZGUgPSBndWlkZV9sZWdlbmQodGl0bGUudGhlbWUgPSBlbGVtZW50X3RleHQoDQogICAgICBzaXplID0gMjApLCBsYWJlbC50aGVtZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMTUpKSkgKw0KICB0aGVtZShheGlzLmxpbmU9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBheGlzLnRleHQueD1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGV4dC55PWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgYXhpcy50aWNrcz1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGl0bGUueD1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIGF4aXMudGl0bGUueT1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIHBhbmVsLmJhY2tncm91bmQ9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBwYW5lbC5ib3JkZXI9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgICBwYW5lbC5ncmlkLm1ham9yPWVsZW1lbnRfYmxhbmsoKSwNCiAgICAgICAgcGFuZWwuZ3JpZC5taW5vcj1lbGVtZW50X2JsYW5rKCksDQogICAgICAgIHBhbmVsLmdyaWQubWFqb3IueCA9IGVsZW1lbnRfbGluZSggc2l6ZT0uMSwgY29sb3I9ImdyZXkiICksDQogICAgICAgIHBhbmVsLmdyaWQubWlub3IueCA9IGVsZW1lbnRfbGluZSggc2l6ZT0uMSwgY29sb3I9ImdyZXkiICksDQogICAgICAgIHBsb3QudGl0bGU9ZWxlbWVudF90ZXh0KHNpemU9MjUsIGhqdXN0PTAsIGZhY2U9ImJvbGQiLCBjb2xvdXI9ImJsYWNrIiwgdmp1c3Q9LTEpLA0KICAgICAgICBwbG90LnN1YnRpdGxlPWVsZW1lbnRfdGV4dChzaXplPTE4LCBoanVzdD0xLCBmYWNlPSJpdGFsaWMiLCBjb2xvcj0iZ3JleSIpLA0KICAgICAgICBwbG90LmNhcHRpb24gPWVsZW1lbnRfdGV4dChzaXplPTE0LCBoanVzdD0xLCBmYWNlPSJpdGFsaWMiLCBjb2xvcj0iZ3JleSIpLA0KICAgICAgICBwbG90LmJhY2tncm91bmQ9ZWxlbWVudF9ibGFuaygpLA0KICAgICAgIHBsb3QubWFyZ2luID0gbWFyZ2luKDIsMiwgMiwgNCwgImNtIikpDQpgYGANCg0KIyBQYXJ0IEM6IEFuaW1hdGluZyB0aGUgc3RhdGljIHBsb3QNCmBgYHtyfQ0KYW5pbWF0ZWQgPC0gc3RhdGljX3Bsb3QgKyB0cmFuc2l0aW9uX3N0YXRlcyh5ZWFyLA0KdHJhbnNpdGlvbl9sZW5ndGggPSAzLCBzdGF0ZV9sZW5ndGggPSAwLCB3cmFwID0gRkFMU0UpICsNCiAgdmlld19mb2xsb3coZml4ZWRfeCA9IFRSVUUpICArDQogIGVhc2VfYWVzKCdsaW5lYXInKSsNCiAgICBlbnRlcl9mYWRlKCkrDQogICAgZXhpdF9mYWRlKCkgKw0KICBsYWJzKHRpdGxlID0gJ1RvcCAzMCBXb3JsZCBHRFAsIDE5NzAtMjAxOScsICANCiAgICAgICBzdWJ0aXRsZSAgPSAgIkdEUCBpbiBCaWxsaW9ucyBVU0QiLA0KICAgICAgIGNhcHRpb24gID0gIkRhdGEgU291cmNlOiBXb3JsZCBCYW5rIERhdGEiKQ0KYGBgDQoNCg0KIyMgUmVuZGVyIHRoZSBhbmltYXRlZCBjaGFydCB0byAuZ2lmIGZpbGUNCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIHdhcm5pbmc9RkFMU0V9DQphbmltYXRlKGFuaW1hdGVkLCAxNTAsIGZwcyA9IDUsIGVuZF9wYXVzZSA9IDMwLCB3aWR0aCA9IDE1MDAsIGhlaWdodCA9IDEwMDAsIA0KICAgICAgICByZW5kZXJlciA9IGdpZnNraV9yZW5kZXJlcigiYW5pbV9nZHAuZ2lmIikpDQpgYGANCg0KDQo=